package com.nuoniu.sibanyun.service.production.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.entity.bo.VoucherDetailBo;
import com.nuoniu.sibanyun.entity.bo.VoucherMainBo;
import com.nuoniu.sibanyun.entity.bo.VoucherSearchBo;
import com.nuoniu.sibanyun.entity.erp.ErpNumberSet;
import com.nuoniu.sibanyun.entity.production.VProductionPickReturnDetail;
import com.nuoniu.sibanyun.entity.production.VProductionPickReturnMain;
import com.nuoniu.sibanyun.entity.production.VProductionPlanDetail;
import com.nuoniu.sibanyun.entity.production.VProductionPlanMain;
import com.nuoniu.sibanyun.entity.so.VSaleDeliveryMain;
import com.nuoniu.sibanyun.entity.so.VSaleOrderDetail;
import com.nuoniu.sibanyun.entity.so.VSaleOrderMain;
import com.nuoniu.sibanyun.mapper.erp.ErpNumberSetMapper;
import com.nuoniu.sibanyun.mapper.production.VProductionPlanMainMapper;
import com.nuoniu.sibanyun.service.crm.ICrmGoodsService;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpNumberSetService;
import com.nuoniu.sibanyun.service.erp.IErpVoucherDesignService;
import com.nuoniu.sibanyun.service.production.IVProductionPlanDetailService;
import com.nuoniu.sibanyun.service.production.IVProductionPlanMainService;
import com.nuoniu.sibanyun.service.so.IVSaleOrderDetailService;
import com.nuoniu.sibanyun.service.so.IVSaleOrderMainService;
import com.nuoniu.sibanyun.service.utils.ErpUtils;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 生产计划主表 服务实现类
 * </p>
 *
 * @author 小啊刚
 * @since 2021-03-11
 */
@Service
public class VProductionPlanMainServiceImpl extends ServiceImpl<VProductionPlanMainMapper, VProductionPlanMain> implements IVProductionPlanMainService {

    @Autowired
    private IErpAccountService accountService;
    @Autowired
    private IVProductionPlanDetailService productionPlanDetailService;
    @Autowired
    private ErpNumberSetMapper numberSetMapper;
    @Autowired
    private IErpNumberSetService numberSetService;
    @Autowired
    private IErpVoucherDesignService erpVoucherDesignService;
    @Autowired
    @Lazy
    private IVSaleOrderMainService saleOrderMainService;
    @Autowired
    private IVSaleOrderDetailService saleOrderDetailService;
    @Autowired
    private ICrmGoodsService crmGoodsService;

    @Override
    @Transactional
    public void saveProductionPlan(VProductionPlanMain productionPlanMain) {
        UserInfo userInfo = UserThreadLocal.get();
        Long mainId = productionPlanMain.getId();
        if(mainId == null) {
            productionPlanMain.setCompanyId(userInfo.getCompanyId());
            productionPlanMain.setAccountId(accountService.getCurrentAccountId());
            productionPlanMain.setCreateUserId(userInfo.getUserId());
            productionPlanMain.setCreateUserName(userInfo.getRealName());
            productionPlanMain.setVoucherCode(getCode());
            productionPlanMain.setVoucherState(-1);
        }else{
            VProductionPlanMain oldVProductionPlanMain = getById(mainId);
            if ( null == oldVProductionPlanMain ) {
                throw new NuoNiuException("修改失败，查询不到记录");
            }
            if ( oldVProductionPlanMain.getVoucherState() > 0) {
                throw new NuoNiuException("该单据已审核，不能修改");
            }
        }
        // 校验 明细数量
        boolean isOk = productionPlanMain.getOrderDetailList().stream().anyMatch(f -> null == f.getBaseQuantity() || !(f.getBaseQuantity().compareTo(BigDecimal.ZERO) > 0));
        if(isOk) {
            throw new NuoNiuException("明细数量必须大于0");
        }
        //计算 明细物料 总数
        List<VProductionPlanDetail> orderDetailList = productionPlanMain.getOrderDetailList();
        BigDecimal totalQuantity =  orderDetailList.stream().map(VProductionPlanDetail::getBaseQuantity).reduce(BigDecimal.ZERO,BigDecimal::add);
        productionPlanMain.setTotalQuantity(totalQuantity.abs());
        Boolean result = this.saveOrUpdate(productionPlanMain);
        if(result) {
            List<Long> detailIds = new ArrayList<>();
            orderDetailList.forEach(p -> {
                p.setCompanyId(userInfo.getCompanyId());
                p.setOrderId(productionPlanMain.getId().intValue());
                p.setAccountId(accountService.getCurrentAccountId());
                //添加 不删除的明细ID
                if (p.getId() != null) {
                    detailIds.add(p.getId());
                }
            });

            //删除明细
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("order_id", productionPlanMain.getId());
            if (detailIds != null && detailIds.size() > 0) {
                wrapper.notIn("id", detailIds);
                productionPlanDetailService.remove(wrapper);
            } else {
                productionPlanDetailService.remove(wrapper);
            }
            //保存单据明细表
            productionPlanDetailService.saveOrUpdateBatch(orderDetailList);
            Long saleOrderId = productionPlanMain.getSaleOrderId();
            //如果 数据来源是 销售订单
            if (null != saleOrderId && mainId == null){
                //1.校验 明细
                List<VSaleOrderDetail> saleOrderDetails = saleOrderDetailService.getDetailsByOrderId(saleOrderId);
                HashMap<Long,VSaleOrderDetail> hashMap = new HashMap<>();
                saleOrderDetails.forEach(vSaleOrderDetail -> hashMap.put(vSaleOrderDetail.getId(),vSaleOrderDetail));
                orderDetailList.forEach(detail->{
                    VSaleOrderDetail vSaleOrderDetail = hashMap.get(detail.getSaleOrderDetailId());
                    if (null == vSaleOrderDetail ) {
                        throw new NuoNiuException("明细数据不匹配，请重新选择销售订单");
                    }
                });

//                saleOrderDetails.forEach(detail->{
//                    VProductionPlanDetail vProductionPlanDetail = hashMap.get(detail.getId());
//                    if (null == vProductionPlanDetail )throw new NuoNiuException("明细数据不匹配，请重新选择销售订单");
//                    if (!vProductionPlanDetail.getInventoryId().equals(detail.getInventoryId()))throw new NuoNiuException("明细物料不匹配，请重新选择销售订单");
//                    if (vProductionPlanDetail.getBaseQuantity().compareTo(detail.getBaseQuantity()) != 0)throw new NuoNiuException("计划明细，物料名称：" + detail.getInventoryName() + ",数量不匹配，应该是："+ detail.getBaseQuantity());
//                });
                List<Long> saleDetailIds = orderDetailList.stream().map(VProductionPlanDetail::getSaleOrderDetailId).collect(Collectors.toList());
                // 2.更新 销售订单 是否
                saleOrderDetailService.updateGenerateWorkPlanStatus(saleOrderId,saleDetailIds,1);
            }
        }
    }
    @Override
    public String getCode() {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = accountService.getCurrentAccountId();
        ErpNumberSet numberSet = numberSetMapper.getByCode("ProductionPlan", userInfo.getCompanyId(), currentAccountId);
        String dateStr = numberSet.getMedian() == 1 ? "%Y-%m-%d" : "%Y-%m";
        String code = baseMapper.getNewestCode(userInfo.getCompanyId(), dateStr);
        return numberSetService.getCode(numberSet, code);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteById(Long id) {
        UserInfo userInfo = UserThreadLocal.get();
        VProductionPlanMain productionPlanMain = getById(id);
        if(productionPlanMain == null) {
            throw new NuoNiuException("单据已删除");
        }
        /**************  修改权限 *******************/
        if(!crmGoodsService.isHaveOperationRight(productionPlanMain.getCreateUserId().longValue())){
            throw new NuoNiuException("你没有权限操作该记录");
        }
        BigDecimal cumExecuteQuantity = productionPlanMain.getCumExecuteQuantity();
        if(null != cumExecuteQuantity && cumExecuteQuantity.compareTo(BigDecimal.ZERO) > 0){
            throw new NuoNiuException("单据已生成下一步单据，不能删除");
        }

        List<VProductionPlanDetail> orderDetails   = productionPlanDetailService.getDetailsByOrderId(id);
        Long saleOrderId = productionPlanMain.getSaleOrderId();
        // 数据来源 销售订单
        if (null != saleOrderId){
            List<Long> saleDetailIds = orderDetails.stream().map(VProductionPlanDetail::getSaleOrderDetailId).collect(Collectors.toList());
            // 1.更新 销售订单
            saleOrderDetailService.updateGenerateWorkPlanStatus(saleOrderId,saleDetailIds,0);
        }
        // *** 如果 来源订单不为空,校验
//        if(null != productionPlanMain.getSourceVoucherId()){
//            VoucherMainBo voucherMainBo = new VoucherMainBo();
//            BeanUtils.copyProperties(productionPlanMain,voucherMainBo);
//            List<VoucherDetailBo> voucherDetailBos = new ArrayList<>();
//            orderDetails.forEach(detail->{
//                VoucherDetailBo voucherDetailBo = new VoucherDetailBo();
//                voucherDetailBos.add(voucherDetailBo);
//                BeanUtils.copyProperties(detail,voucherDetailBo);
//            });
//            VoucherSearchBo voucherSearchBo = new VoucherSearchBo();
//            voucherSearchBo.setCalculateType(2);
//            voucherSearchBo.setSourceVoucherId(productionPlanMain.getSourceVoucherId());
//            voucherSearchBo.setSourceVoucherType(productionPlanMain.getSourceVoucherType());
//            voucherSearchBo.setVoucherId(productionPlanMain.getId().intValue());
//            voucherSearchBo.setVoucherType("ProductionPlan");
//            erpVoucherDesignService.calculateSourceVoucher(voucherMainBo,voucherDetailBos,voucherSearchBo);
//        }
        removeById(id);
        productionPlanDetailService.removeByOrderId(id);
    }

    @Override
    public Map getOrderList() {
        QueryWrapper wrapper = new QueryWrapper();
        Map<String, Object> data = new HashMap<>();
        UserInfo userInfo = UserThreadLocal.get();

        wrapper.eq("company_id", UserThreadLocal.get().getCompanyId());
        wrapper.eq("account_id", accountService.getCurrentAccountId());
        wrapper.eq("is_operation", 0);
        wrapper.eq("voucher_state", 1);
        List<VProductionPlanMain> productionPlanMains = this.list(wrapper);
        List<VProductionPlanDetail> productionPlanDetails = productionPlanDetailService.getList(userInfo.getCompanyId());
        data.put("saleOrderMain", productionPlanMains);
        data.put("saleOrderDetail", productionPlanDetails);
        return data;
    }

    @Override
    public void submit(Long id, Integer status) {
        if(null == id || null == status || (status > 0 || status < -1 )) {
            throw new NuoNiuException("参数错误");
        }
        UserInfo userInfo = UserThreadLocal.get();
        VProductionPlanMain main = this.getById(id);
        if( null == main) {
            throw new NuoNiuException("记录不存在");
        }
        //校验状态
        Integer voucherState = main.getVoucherState();
        /**  统一校验 提交状态 */
        ErpUtils.checkSubmitStatus(voucherState,status);
        //提交
        main.setVoucherState(status);
        main.setSubmitDate(LocalDateTime.now());
        main.setSubmitUserId(userInfo.getUserId());
        main.setSubmitUserName(userInfo.getRealName());
        this.updateById(main);
    }

    @Override
    public void examine(Long id, Integer status) {
        if(null == id || null == status ||  (status > 1 || status < 0) ) {
            throw new NuoNiuException("参数错误");
        }
        UserInfo userInfo = UserThreadLocal.get();
        VProductionPlanMain orderMain = getById(id);
        if (null == orderMain) {
            throw new NuoNiuException("查询不到记录");
        }
        BigDecimal cumExecuteQuantity = orderMain.getCumExecuteQuantity();
        Integer voucherState = orderMain.getVoucherState();
        /** 统一校验 审核状态*/
        ErpUtils.checkExamineStatus(voucherState,status,cumExecuteQuantity);

        VProductionPlanMain productionPlanMain = new VProductionPlanMain();
        productionPlanMain.setVoucherState(status);
        productionPlanMain.setId(id);
        productionPlanMain.setReviewerDate(LocalDateTime.now());
        productionPlanMain.setReviewerUserId(userInfo.getUserId());
        productionPlanMain.setReviewerUserName(userInfo.getRealName());
        updateById(productionPlanMain);
    }
}
